/** * Java Diagram Package; An extremely flexible and fast multipurpose diagram component for Swing. Copyright (C) 2001 Eric Crahen <crahen@cse.buffalo.edu> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package diagram.tool; import java.awt.event.MouseEvent; import java.awt.geom.Point2D; import javax.swing.event.MouseInputAdapter; import diagram.Diagram; import diagram.DiagramUI; import diagram.Figure; import diagram.Link; import diagram.figures.PointFigure; import diagram.figures.PolyLink; /** * @class LinkTool * * @date 08-20-2001 * @author Eric Crahen * @version 1.0 * * This tool allows a Link to be added to a Diagram model. The Link must * be anchored in a (non-Link) Figure and its sink will be at the current * mouse position until it can be placed into another (non-Link) Figure */ public class LinkTool extends AbstractTool { private final static double POINT_SIZE = 5; private Diagram diagram; private Figure figSource; private Figure figSink; private PointFigure ptSink = new PointFigure(POINT_SIZE); private Point2D ptCenter; private Link link; private MouseHandler mouseHandler = new MouseHandler(); /** * Install support for something in the given Diagram * * @param Diagram */ public void install(Diagram diagram) { diagram.addMouseListener(mouseHandler); diagram.addMouseMotionListener(mouseHandler); } /** * Remove support for something that was previously installed. * * @param Diagram */ public void uninstall(Diagram diagram) { diagram.removeMouseListener(mouseHandler); diagram.removeMouseMotionListener(mouseHandler); reset(); } protected class MouseHandler extends MouseInputAdapter { /** * Mouse pressed. * * @param MouseEvent */ public void mousePressed(MouseEvent e) { // Start the drag Object o = e.getSource(); if(!e.isConsumed() && e.getClickCount() == 1 && (o instanceof Diagram)) { diagram = (Diagram)o; // Find the figure clicked on Point2D pt = e.getPoint(); if(((figSource = (Figure)diagram.findFigure(pt)) == null) || (figSource instanceof Link)) { reset(); return; } e.consume(); fireToolStarted(); // Create an end point to drag the line with for now... ptSink.setLocation(pt.getX(), pt.getY()); link = createLink(figSource, ptSink); // Display the link diagram.getModel().add(link); // The moving endpoint is not considered related DiagramUI ui = (DiagramUI)diagram.getUI(); ui.removeConnection(ptSink, link); } } /** * Mouse dragged. * * @param MouseEvent */ public void mouseDragged(MouseEvent e) { if(diagram == null) return; Point2D pt = e.getPoint(); DiagramUI ui = (DiagramUI)diagram.getUI(); // Damage the link that is moving ui.damageFigure(link); // Find the figure beneath the mouse, attach the link if possible // The figure is not another link, the figure is not the source figure // and the figure is not the sink fiure Figure sink = (Figure)diagram.findFigure(pt); if(sink != null && !(sink instanceof Link) && sink != figSource && sink != figSink) { ui.addConnection(sink, link); link.setSink(sink); figSink = sink; // Otherwise, attach to the sink point & move it } else if(sink != figSink) { ptSink.setLocation(pt.getX(), pt.getY()); // Attach the sink point if needed, remove the connection to the last figure if(figSink != ptSink) { ui.removeConnection(link.setSink(ptSink), link); figSink = ptSink; } } ui.refreshFigure(link); } /** * Mouse released. * * @param MouseEvent */ public void mouseReleased(MouseEvent e) { if(diagram == null) return; e.consume(); DiagramUI ui = (DiagramUI)diagram.getUI(); ui.damageFigure(link); // If the link was not anchored (or never moved), remove it if(figSink == null || figSink == ptSink) diagram.getModel().remove(link); else { // Replace the link if needed Link finalLink = finalizeLink(link); if(finalLink != link) { diagram.getModel().remove(link); diagram.getModel().add(finalLink); } ui.refreshFigure(finalLink); } fireToolFinished(); reset(); } } /* MouseHandler */ /** * Cleanup */ protected void reset() { diagram = null; figSink = null; figSource = null; link = null; } /** * Create the Figure for the link * * @param Figure source end * @param Figure sink end * * @return Link */ protected Link createLink(Figure source, Figure sink) { return new PolyLink(source, sink); } /** * This method provides an opportunity to replace the link when the shapping is done. * * @param Link * @return Link */ protected Link finalizeLink(Link link) { return link; } }